package LunaServer.core;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Callable;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.nio.file.Files;
import java.nio.file.Paths;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import LunaServer.config.ConfigManager;
import LunaServer.logging.Logger;
import LunaServer.routing.Route;
import LunaServer.routing.RouteHandler;

// 一个服务器类。这个服务器类必须内嵌所有参数，包括json解析。
public class LunaServer {

    private HttpServer server;
    private Map<String, String> fileRoutes = new HashMap<>(); // 存储路由路径到文件路径的映射
    private Set<String> builtInRoutes = new HashSet<>(); // 存储内置路由路径，防止被删除
    private String dbUrl;
    private String dbUser;
    private String dbPass;
    private boolean dbConnected = false;
    private String dbStatus = "未连接";
    private ConfigManager configManager;
    private AccountHandler accHandler;

    // 数据库上下文。
    private Connection connection = null;

    // 日志记录器
    private Logger logger = Logger.getInstance();

    /*
     * 初始化服务器，加载配置
     */
    public LunaServer() {
        configManager = new ConfigManager();
        // 从配置文件加载数据库配置
        dbUrl = configManager.getProperty("database.url", "jdbc:postgresql://127.0.0.1:1980/postgres");
        dbUser = configManager.getProperty("database.user", "postgres");
        dbPass = configManager.getProperty("database.password", "lunamoon");
        accHandler = new AccountHandler();

        // 初始化日志记录器
        logger.info("LunaServer initializing");
    }

    /*
     * 启动服务器。
     * 
     * @args port: 服务器开启后使用的端口号。
     */
    public void startServer(int port) throws IOException {
        server = HttpServer.create(new InetSocketAddress(port), 0);

        // 测试数据库连接
        testDatabaseConnection();

        // 为文件路由创建上下文
        setupFileRoutes();

        server.setExecutor(null); // 使用默认单线程执行器
        server.start();
        logger.info("HTTP Server started on port " + port);
        logger.info("Database status: " + dbStatus);
    }

    /*
     * 测试数据库连接
     */
    private void testDatabaseConnection() {

        try {
            // 建立数据库连接
            this.connection = DriverManager.getConnection(dbUrl, dbUser, dbPass);
            dbConnected = connection.isValid(5); // 5秒超时

            if (dbConnected) {
                // 执行简单查询
                Statement statement = connection.createStatement();
                ResultSet resultSet = statement.executeQuery("SELECT version()");

                if (resultSet.next()) {
                    dbStatus = "连接成功 - PostgreSQL版本: " + resultSet.getString(1);
                } else {
                    dbStatus = "连接成功";
                }
            } else {
                dbStatus = "连接失败";
            }
        } catch (SQLException e) {
            dbConnected = false;
            dbStatus = "连接错误: " + e.getMessage();
            logger.error("Database connection error: " + e.getMessage());
        } finally {
            // 关闭数据库连接
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    logger.error("关闭数据库连接时发生错误: " + e.getMessage());
                }
            }
        }
    }

    /*
     * 为服务器添加路由。
     * Args:
     * String path: 路由路径。
     * Callable<String>: 处理函数。
     */
    public void newContext(String path, Callable<String> handler) {
        server.createContext(path, exchange -> {
            String response = "";
            try {
                response = handler.call();
            } catch (Exception e) {
                response = "Error: " + e.getMessage();
            }
            exchange.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes());
            os.close();
        });
    }

    /*
     * 删除服务器路由
     * Args:
     * String path: 要删除的路由路径
     * Returns:
     * boolean: 删除成功返回true，如果路由不存在或为内置路由则返回false
     */
    public boolean removeContext(String path) {
        // 检查是否为内置路由
        if (builtInRoutes.contains(path)) {
            logger.warn("Cannot remove built-in route: " + path);
            return false;
        }

        // 移除文件路由映射（如果是文件路由）
        fileRoutes.remove(path);

        // 从服务器移除上下文
        try {
            server.removeContext(path);
            logger.info("Route removed: " + path);
            return true;
        } catch (IllegalArgumentException e) {
            // 路由不存在
            logger.warn("Route does not exist: " + path);
            return false;
        }
    }

    /*
     * 添加文件路由
     * Args:
     * String path: 路由路径
     * String filePath: 处理该路由的文件路径
     */
    public void addFileRoute(String path, String filePath) {
        fileRoutes.put(path, filePath);
        // 如果服务器已经启动，需要重新设置文件路由
        if (server != null) {
            setupFileRoute(path, filePath);
        }
    }

    /*
     * 设置文件路由
     */
    private void setupFileRoutes() {
        for (Map.Entry<String, String> entry : fileRoutes.entrySet()) {
            setupFileRoute(entry.getKey(), entry.getValue());
        }
    }

    /*
     * 为单个路由设置文件处理
     */
    private void setupFileRoute(String path, String filePath) {
        server.createContext(path, exchange -> {
            try {
                // 使用RouteHandler处理路由文件
                String response = RouteHandler.handleRouteFromFile(this, filePath, exchange, false);
                // 注意：响应内容已经在Route实现中通过exchange.sendResponseHeaders发送
                // 但如果handleRouteFromFile返回了内容，我们需要将其写入输出流
                if (response != null) {
                    OutputStream os = exchange.getResponseBody();
                    os.write(response.getBytes(java.nio.charset.StandardCharsets.UTF_8));
                    os.close();
                }
            } catch (Exception e) {
                String errorResponse = "Error handling route: " + e.getMessage();
                exchange.sendResponseHeaders(500, errorResponse.getBytes().length);
                OutputStream os = exchange.getResponseBody();
                os.write(errorResponse.getBytes());
                os.close();
            }
        });
    }

    /*
     * 重载路由配置（热重载）
     * 清除当前所有非内置路由，并重新加载路由配置
     */
    public void reloadRoutes(Map<String, String> newFileRoutes) {
        // 移除所有非内置路由
        // 注意：HttpServer没有直接获取所有上下文的方法，所以我们需要跟踪我们自己创建的上下文
        for (String path : new HashSet<>(fileRoutes.keySet())) {
            if (!builtInRoutes.contains(path)) {
                try {
                    server.removeContext(path);
                } catch (IllegalArgumentException e) {
                    // 路由可能不存在，忽略错误
                }
            }
        }

        // 清空当前文件路由映射
        fileRoutes.clear();

        // 清除RouteHandler的类缓存，确保重新编译路由处理文件
        RouteHandler.clearAllCache();

        // 添加新的文件路由
        this.fileRoutes = new HashMap<>(newFileRoutes);
        setupFileRoutes();

        logger.info("Routes reloaded successfully");
    }

    /*
     * 获取所有文件路由
     */
    public Map<String, String> getFileRoutes() {
        return new HashMap<>(fileRoutes);
    }

    /*
     * 获取数据库状态
     */
    public String getDatabaseStatus() {
        return dbStatus;
    }

    /*
     * 停止服务器。
     */
    public void stopServer() {
        if (server != null) {
            server.stop(0);
            logger.info("HTTP Server stopped");
            // 关闭日志记录器
            logger.shutdown();
        }
    }

    /*
     * 设置数据库连接参数
     */
    public void setDatabaseConfig(String url, String user, String password) {
        this.dbUrl = url;
        this.dbUser = user;
        this.dbPass = password;
    }

    // 返回服务器数据库连接上下文
    public Connection getDatabaseConnection() throws SQLException {
        return DriverManager.getConnection(dbUrl, dbUser, dbPass);
    }

    /*
     * 获取数据库URL
     */
    public String getDbUrl() {
        return dbUrl;
    }

    /*
     * 获取数据库用户名
     */
    public String getDbUser() {
        return dbUser;
    }

    /*
     * 获取数据库密码
     */
    public String getDbPass() {
        return dbPass;
    }
}

// 账号处理器类
class AccountHandler {
    public AccountHandler() {
        // 构造函数
    }

    public void parseRequest(String requestBody) {
        // 解析请求的实现
        System.out.println("Parsing request: " + requestBody);
    }
}